package com.by.wx.service;

import java.awt.font.TextMeasurer;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;
import javax.servlet.ServletInputStream;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.baidu.aip.ocr.AipOcr;
import com.by.wx.entity.AccessToken;
import com.by.wx.entity.Article;
import com.by.wx.entity.BaseMessage;
import com.by.wx.entity.ImageMessage;
import com.by.wx.entity.MusicMessage;
import com.by.wx.entity.NewsMessage;
import com.by.wx.entity.TextMessage;
import com.by.wx.entity.VideoMessage;
import com.by.wx.entity.VoiceMessage;
import com.by.wx.util.Util;
import com.by.wx.util.UtilsA;
import com.thoughtworks.xstream.XStream;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class WxService {
	private static final String TOKEN = "bytoken";
	private static final String APPKEY = "bytoken???";

	private static final String GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	private static final String APPID = "wx6bfaf2e1c5a32265";
	private static final String APPSECRET = "c3d56607647a712ee59af21873660e51";
	//用户存储token
	private static AccessToken at;
	
	//设置APPID/AK/SK- ---百度AI
    public static final String APP_ID = "15466781";
    public static final String API_KEY = "bGjd5AKRdmgbX8yGfgws7wLi";
    public static final String SECRET_KEY = "5P7CxfmGbVHA41Lftq4K17xd5a4T2zlS";
    
    
	/**
	 * 获取token
	 */
	private static void getToken(){
		String url = GET_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
		String tokenStr = Util.get(url);
//		System.out.println(tokenStr);
		JSONObject jsonObject = JSONObject.fromObject(tokenStr);
		String token = jsonObject.getString("access_token");
		String expireIn = jsonObject.getString("expires_in");
		at = new AccessToken(token, expireIn);
	}
	/**
	 * 向外暴露获取token的方法
	 * @return
	 */
	public static String getAccessToken(){
		if (at == null || at.isExpried()) {
			getToken();
		}
		return at.getAccessToken();
	}
	
	/**
	 * 验证签名
	 * @param timestamp
	 * @param nonce
	 * @param echostr
	 * @return
	 */
	public static boolean check(String timestamp, String nonce, String signature) {
		// 1）将token、timestamp、nonce三个参数进行字典序排序
		String[] strs = new String[] { TOKEN, timestamp, nonce };
		Arrays.sort(strs);
		// 2）将三个参数字符串拼接成一个字符串进行sha1加密
		String str = strs[0] + strs[1] + strs[2];
		String mysig = sha1(str);
		// 3）开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
//		System.out.println(mysig);
//		System.out.println(signature);
		return mysig.equalsIgnoreCase(signature);
	}

	/**
	 * 进行sha1加密
	 * @param str
	 * @return
	 */
	private static String sha1(String src) {
		try {
			//获取一个加密对象
			MessageDigest md = MessageDigest.getInstance("sha1");
			//加密
			byte[] digest = md.digest(src.getBytes());
			char[] chars = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
			StringBuffer sb = new StringBuffer();
			//处理加密结果
			for (byte b : digest) {
				sb.append(chars[(b >> 4) &15]);
				sb.append(chars[b &15]);
			}
			return sb.toString();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		
		return null;
	}


	/**
	 * 解析xml数据包
	 * @param is
	 * @return
	 */
	public static Map<String, String> parseRequest(ServletInputStream is) {
		Map<String , String> map =new HashMap<>();
		SAXReader reader = new SAXReader();
		try {
			//读取输入流，获取文档对象
			Document document = reader.read(is);
			//根据文档对象获取根节点
			Element root = document.getRootElement();
			//获取根节点的所有子节点
			List<Element> elements = root.elements();
			for (Element e : elements) {
				map.put(e.getName(), e.getStringValue());
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		
		return map;
	}

	public static String getRespose(Map<String, String> requestMap) {
		BaseMessage msg = null;
		String MsgType = requestMap.get("MsgType");
		switch (MsgType) {
		case "text":
			msg = dealTextMessage(requestMap);
			break;
		case "image":
			msg = dealImage(requestMap);
			break;
		case "voice":
			break;
		case "video":
			break;
		case "shortvideo":
			break;
		case "location":
			break;
		case "link":
			break;
		case "event":
			msg = dealEvent(requestMap);
			break;

		default:
			break;
		}
		if (msg != null) {
			return beanToXml(msg);
		} else {
			return null;
		}
	}
	/**
	 * 进行图片识别
	 * @param requestMap
	 * @return
	 */
	private static BaseMessage dealImage(Map<String, String> requestMap) {
		// 初始化一个AipOcr
        AipOcr client = new AipOcr(APP_ID, API_KEY, SECRET_KEY);

        // 可选：设置网络连接参数
        //client.setConnectionTimeoutInMillis(2000);
        //client.setSocketTimeoutInMillis(60000);

        // 可选：设置代理服务器地址, http和socket二选一，或者均不设置
        //client.setHttpProxy("proxy_host", proxy_port);  // 设置http代理
        //client.setSocketProxy("proxy_host", proxy_port);  // 设置socket代理

        // 可选：设置log4j日志输出格式，若不设置，则使用默认配置
        // 也可以直接通过jvm启动参数设置此环境变量
        //System.setProperty("aip.log4j.conf", "path/to/your/log4j.properties");

        // 调用接口
        String path = requestMap.get("PicUrl");
        
        //这里只能调用本地的图片进行识别
//        org.json.JSONObject res = client.basicGeneral(path, new HashMap<String, String>());
        //进行网络图片的识别
        org.json.JSONObject res = client.generalUrl(path, new HashMap<String,String>());
        String json = res.toString();
        //转为jsonObject
        JSONObject jsonObject= JSONObject.fromObject(json);
        JSONArray jsonArray = jsonObject.getJSONArray("words_result");
        Iterator<JSONObject> it = jsonArray.iterator();
        StringBuilder sb = new StringBuilder();
        while(it.hasNext()){
        	JSONObject next = it.next();
        	sb.append(next.getString("words"));
        }
		return new TextMessage(requestMap, sb.toString());
	}
	/**
	 * 处理事件推送
	 * @param requestMap
	 * @return
	 */
	private static BaseMessage dealEvent(Map<String, String> requestMap) {
		String event = requestMap.get("Event");
		switch(event) {
		case "CLICK":
			return dealClick(requestMap);
		case "":
			return dealView(requestMap);
		default:
			break;
		}
		return null;
	}
	/**
	 * 专门用来处理view菜单
	 * @param requestMap
	 * @return
	 */
	private static BaseMessage dealView(Map<String, String> requestMap) {
		// TODO Auto-generated method stub
		return null;
	}
	/**
	 * 专门用来处理click菜单
	 * @param requestMap
	 * @return
	 */
	private static BaseMessage dealClick(Map<String, String> requestMap) {
		String key = requestMap.get("EventKey");
		switch(key){
			//点击一级菜单
			case "1":
			//处理点击了第一个一级菜单
				return new TextMessage(requestMap, "你点了一下第一个一级菜单");
			case "32":
				//处理点击了第三个一级菜单的第二个子菜单
				break;
			default:
				break;
		}
		return null;
	}
	private static String beanToXml(BaseMessage msg) {
		XStream stream = new XStream();
		stream.processAnnotations(TextMessage.class);
		stream.processAnnotations(ImageMessage.class);
		stream.processAnnotations(MusicMessage.class);
		stream.processAnnotations(NewsMessage.class);
		stream.processAnnotations(VideoMessage.class);
		stream.processAnnotations(VoiceMessage.class);
		String xml = stream.toXML(msg);
		return xml;
	}

	private static BaseMessage dealTextMessage(Map<String, String> requestMap) {
		//用户发来的内容
		String msg = requestMap.get("Content");
		if(msg.equals("图文")){
			List<Article> articles =new ArrayList<>();
			articles.add(new Article("这是图文消息", "介绍", "https://image.baidu.com/search/detail?z=0&ipn=d&word=tup&step_word=&hs=0&pn=0&spn=0&di=0&pi=&tn=baiduimagedetail&is=0%2C0&istype=&ie=utf-8&oe=utf-8&cs=436693990%2C4197026682&os=3675426342%2C2297754408&simid=&adpicid=0&lpn=0&fm=&sme=&cg=&bdtype=0&simics=4135477902%2C3355939884&oriquery=&objurl=https%3A%2F%2Ftimgsa.baidu.com%2Ftimg%3Fimage%26quality%3D80%26size%3Db10000_10000%26sec%3D1545988000%26di%3De55e5beb26f2d30ccebc6f9273c957ab%26src%3Dhttp%3A%2F%2Fimg.qqzhi.com%2Fupload%2Fimg_3_2604932212D3118441053_27.jpg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bqqc9c_z%26e3Bv54AzdH3FxtgojgAzdH3F454tg3wg%2Bda80_z%26e3Bip4s&gsm=0&islist=&querylist=&cardserver=1", 
					"http://www.baidu.com"));
			NewsMessage nm =new NewsMessage(requestMap,  articles);
			return nm;
		}
		if (msg.equals("登录")) {
			String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
			url = url.replace("APPID", APPID).replace("REDIRECT_URI", "http://lssweixin.free.idcfengye.com/wxapp/GetUserInfo").replace("SCOPE", "snsapi_userinfo");
			TextMessage tm = new TextMessage(requestMap, "点击<a href=\""+url+"\">这里</a>登录");
			return tm;
		}
		String resp = chat(msg);
//		TextMessage tm =new TextMessage(requestMap, "hello");
		TextMessage tm =new TextMessage(requestMap, resp);
		return tm;
	}

	/**
	 * 调用图灵机器人聊天
	 * @param msg  发送的消息
	 * @return
	 */
	private static String chat(String msg) {
		String result = null;
		String url = "http://op.juhe.cn/robot/index";//请求接口地址
		Map params = new HashMap();//请求参数
		params.put("key", APPKEY);//您申请到的本接口专用的APPKEY
		params.put("info", msg);//要发送给机器人的内容，不要超过30个字符
		params.put("dtype", "");//返回的数据格式，json或xml，默认为json
		params.put("loc", "");//低点，如北京中关村
		params.put("lon", "");//经度，东经116.234632（小数）
		params.put("lat", "");//纬度，北纬40.234632
		params.put("userid", "");//1~32位，此userid针对您自己的每一个客户，用于上下文的关系
		
		try {
			result = Util.net(url, params, "GET");
			//解析json
			JSONObject jsonObject = JSONObject.fromObject(result);
			//去除error_code
			int code = jsonObject.getInt("error_code");
			if (code !=0) {
				return null;
			}
			//取出返回的消息的内容
			String resp = jsonObject.getJSONObject("result").getString("text");
			return resp;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 上传临时素材
	 * @param path 上传的文件的路径
	 * @param type 上传的文件的类型
	 * @return
	 */
	public static String upload(String path,String type) {
		File file = new File(path);
		//地址
		String url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
		url = url.replace("ACCESS_TOKEN", getAccessToken()).replace("TYPE", type);
		try {
			URL urlObj = new URL(url);
			//强转为安全连接
			HttpsURLConnection conn = (HttpsURLConnection) urlObj.openConnection();
			//设置连接的信息
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setUseCaches(false);
			//设置请求头信息
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Charset", "utf8");
			//数据的边界
			String boundary = "-----"+System.currentTimeMillis();
			conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
			//获取输出流
			OutputStream out = conn.getOutputStream();
			//创建文件的输入流
			InputStream is = new FileInputStream(file); 
			//第一部分：头部信息
			//准备头部信息
			StringBuilder sb = new StringBuilder();
			sb.append("--");
			sb.append(boundary);
			sb.append("\r\n");
			sb.append("Content-Disposition:form-data;name=\"media\";filename=\""+file.getName()+"\"\r\n");
			sb.append("Content-Type:application/octet-stream\r\n\r\n");
			out.write(sb.toString().getBytes());
			System.out.println(sb.toString());
			//第二部分：文件内容
			byte [] b =new byte[1024];
			int len;
			while((len=is.read(b))!=-1){
				out.write(b,0,len);
			}
			//第三部分：尾部信息
			String foot="\r\n--"+boundary+"--\r\n";
			out.write(foot.getBytes());
			out.flush();
			out.close();
			//读取数据
			InputStream is2 = conn.getInputStream();
			StringBuilder resp =new StringBuilder();
			while((len=is2.read(b))!=-1){
				resp.append(new String(b,0,len));
			}
			return resp.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 获取带参数二维码的ticket
	 * @return
	 */
	public static String getQrCodeTicket() {
		String at = getAccessToken();
		String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
		url =url.replace("TOKEN", at);
		//生成临时字符串二维码
		String data = "{\"expire_seconds\": 604800, \"action_name\": \"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"baoya\"}}}";
		String reuslt = UtilsA.post(url, data);
		String ticket = JSONObject.fromObject(reuslt).getString("ticket");
		return ticket;
	}
	
	/**
	 * 获取用户的基本信息
	 * @param openid
	 * @return
	 */
	public static String getUserInfo(String openid) {
		String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
		url = url.replace("ACCESS_TOKEN", getAccessToken()).replace("OPENID", openid);
		String result = UtilsA.get(url);
		return result;
	}
}
